# coding: utf8
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.image import MIMEImage
from email.header import Header
from email.utils import parseaddr, formataddr
import smtplib

"""
QQEmailClient module.

Created on 12/29/2017

@author: 强哥
"""

STMP_SERVER = "smtp.exmail.qq.com" # 企业邮箱地址
STMP_SERVER2 = "smtp.qq.com" # QQ邮箱地址
STMP_PORT = 465
MAIL_FROM = "shoulong@zhibo8.cc"
PASSWD = "zB8123456789" # 或者QQ邮件发送授权码
CONTENT_TYPE = "html"
ENCODING = "utf-8"
SUCCESS_INFO = "Login Server Success!"
FAILD_INFO = "Login Server Faild!"
SEND_SUCCESS_INFO = "Send message Success!"
SEND_FAILD_INFO = "Send message Faild!"
HTML_FORMAT = "<html><head></head><body><table><tbody>%s</tbody></table></body></html>"
IMAGE_FORMAT = '<td><img src="cid:%s"></td>'
TR_FORMAT = "<tr>%s</tr>"

class QQEmailClient(object):
    """

    发送QQ邮件客户端
    """

    def __init__(self, mail_from='', mail_pwd=''):
        self.title      = '监控邮件'
        self.mailTo     = ''
        self.__mailFrom = mail_from or MAIL_FROM
        self.__passwd   = mail_pwd or PASSWD
        self.__message  = None
        self.__text     = '强哥送来问候'
        self.__server   = None
        self.__fileName = ''
        self.__imageNames = []

    def __set_email_init(self, **kw):
        self.mailTo         = kw.get('mailTo')
        self.__text         = kw.get('text', '')
        self.__fileName     = kw.get('fileName', '')
        self.__imageNames   = kw.get('imageNames', [])


    def __addFile(self):
        """
        
        构造附件
        """
        msgFile = MIMEText(open(self.__fileName, 'rb').read(), 'base64', ENCODING)
        msgFile["Content-Type"] = 'application/octet-stream'
        msgFile["Content-Disposition"] = 'attachment; filename=%s' % self.__fileName
        return msgFile

    def __addText(self):
        """

        构造预览信息
        """
        self.__setContentHtml()
        return MIMEText(self.__text, CONTENT_TYPE, ENCODING)

    def __addImage(self, src, imageId):
        """

        构造图片
        """
        with open(src, 'rb') as f:
            msgImage = MIMEImage(f.read())
        msgImage.add_header('Content-ID', imageId)
        return msgImage

    def __messageInit(self):
        """

        构造邮件信息
        """
        self.__message = MIMEMultipart()
        name, addr = parseaddr('来自脚本<%s>' % self.__mailFrom)
        self.__message['From'] = formataddr((Header(name, ENCODING).encode(), addr))
        self.__message['To'] = ','.join(self.mailTo)
        self.__message['Subject'] = Header(self.title, ENCODING)

        if self.__fileName:
            self.__message.attach(self.__addFile())
        if self.__imageNames:
            for num, src in enumerate(self.__imageNames):
                self.__message.attach(self.__addImage(src, str(num)))
            self.__text = self.__setImageHtml(len(self.__imageNames)) + self.__text
        
        self.__message.attach(self.__addText())

    def __makeSTMPServer(self):
        """
        
        创建邮件连接服务实例
        """
        self.__server = smtplib.SMTP_SSL(STMP_SERVER, STMP_PORT)

    def __loginServer(self):
        """

        登录邮件服务端
        """
        self.__makeSTMPServer()
        try:
            self.__server.login(self.__mailFrom, self.__passwd)
            print(SUCCESS_INFO)
            return True
        except Exception as e:
            print(e)
            print(FAILD_INFO)
            self.__server.quit()
            return False

    def __sendEmail(self):
        """

        发送邮件
        """
        try:
            self.__messageInit()
            self.__server.sendmail(self.__mailFrom, self.mailTo, self.__message.as_string())
            print(SEND_SUCCESS_INFO)
        except Exception as e:
            print(e)
            print(SEND_FAILD_INFO)

    def __setImageHtml(self, num):
        """
        
        存放图片的html容器, 此时图片还没有进来
        """
        # 每个图片放在一个td里面
        images = [IMAGE_FORMAT % i for i in range(num)] 

        # 每两个 <td> 放进一个 <tr> 中
        if num == 1:
            imagesStr = TR_FORMAT % ''.join(images[0])
        elif num % 2 != 0:  # 奇数个图片
            imagesStr = ''.join([TR_FORMAT % ''.join(i) for i in zip(images[::2], images[1::2])])
            imagesStr += TR_FORMAT % ''.join(images[-1])
        else:               # 偶数数个图片
            imagesStr = ''.join([TR_FORMAT % ''.join(i) for i in zip(images[::2], images[1::2])])

        return HTML_FORMAT % imagesStr

    def __setContentHtml(self):
        """

        预览信息内容
        """
        return HTML_FORMAT % self.__text

    def send(self, **kw):
        """
        
        函数主体
        """
        self.__set_email_init(**kw)
        if self.__loginServer():
            self.__sendEmail()
            self.__server.quit()

def example():
    """

    例子
    """
    mailTo = ['576879814@qq.com']
    text = "测试一下"
    fileName = "README.md"
    # imageNames = ['01.jpg']
    Email = QQEmailClient('shoulong@zhibo8.cc', 'zB8123456789')
    Email.send(mailTo=mailTo, text=text)

if __name__ == '__main__':
    example()